package com.eddie.factorybean;

import com.eddie.annotation.TenantSelector;
import com.eddie.cglib.TenantSelectorMethodInterceptor;
import net.sf.cglib.proxy.Enhancer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * @author Eddie
 */
public class TenantSelectorFactoryBean<T> implements FactoryBean<T>, ApplicationContextAware {
    private final Class<T> superclass;
    private final TenantSelectorMethodInterceptor methodInterceptor;
    private ApplicationContext ac;
    List<Class<? extends T>> subclasses;

    public TenantSelectorFactoryBean(Class<T> superclass, List<Class<? extends T>> subclasses) {
        this.superclass = superclass;
        this.methodInterceptor = new TenantSelectorMethodInterceptor();
        this.subclasses = subclasses;
    }

    @Override
    public T getObject() throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(superclass);
        enhancer.setCallback(methodInterceptor);
        return (T) enhancer.create();
    }

    @Override
    public Class<?> getObjectType() {
        return superclass;
    }

    @PostConstruct
    public void buildMatBean() {
        for (Class<? extends T> subclass : subclasses) {
            TenantSelector martSelector = subclass.getAnnotation(TenantSelector.class);
            methodInterceptor.addBean(martSelector.value(), ac.getBean(subclass));
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ac = applicationContext;
    }
}
